<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2011 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: luofei614 <weibo.com/luofei614>　
// +----------------------------------------------------------------------
namespace Common\Lib\Think;
use Admin\Model\AdminModel;

class XAuth{

    //默认配置
    protected $_config = array(
        'AUTH_ROLE'         => 'auth_role',             // 角色数据表名
        'AUTH_ROLE_USER'    => 'auth_role_user',        // 用户-角色关系表
        'AUTH_RULE'         => 'auth_rule',            // 权限规则表
        'AUTH_ACCESS'       => 'auth_access',            // 权限规则表
        'AUTH_USER'         => 'admin'                  // 用户信息表
    );

    public function __construct() {
        $prefix = C('DB_PREFIX');
        $this->_config['AUTH_ROLE'] = $prefix.$this->_config['AUTH_ROLE'];
        $this->_config['AUTH_ROLE_USER'] = $prefix.$this->_config['AUTH_ROLE_USER'];
        $this->_config['AUTH_RULE'] = $prefix.$this->_config['AUTH_RULE'];
        $this->_config['AUTH_ACCESS'] = $prefix.$this->_config['AUTH_ACCESS'];
        $this->_config['AUTH_USER'] = $prefix.$this->_config['AUTH_USER'];
    }

    /**
     * 检查权限
     * @param uid  int           认证用户的id
     * @param name string|array  需要验证的规则列表,支持逗号分隔的权限规则或索引数组
     * @param relation string    如果为 'or' 表示满足任一条规则即通过验证;如果为 'and'则表示需满足所有规则才能通过验证
     * @return boolean           通过验证返回true;失败返回false
     */
    public function check($uid, $name, $relation='or') {
        if (empty($uid)) return false;
        if (intval($uid) == AdminModel::DEFAULT_ADMIN) return true;

        if (is_string($name)) {
            $name = strtolower($name);
            if (strpos($name, ',') !== false) {
                $name = explode(',', $name);
            } else {
                $name = array($name);
            }
        }
        $groups = $this->getGroups($uid);
        if(in_array(AdminModel::DEFAULT_ADMIN_ROLE, $groups)){
            return true;
        }

        if(empty($groups)){
        	return false;
        }
        $authList = $this->getAuthList($uid, $groups, $name);

        $list = array(); //保存验证通过的规则名

        foreach ($authList as $rule){
            if (!empty($rule['condition'])) { //根据condition进行验证
                $user = $this->getUserInfo($uid);//获取用户信息,一维数组

                $command = preg_replace('/\{(\w*?)\}/', '$user[\'\\1\']', $rule['condition']);

                @(eval('$condition=(' . $command . ');'));
                if ($condition) {
                    $list[] = strtolower($rule['name']);
                }
            }else{
                $list[] = strtolower($rule['name']);
            }
        }

        if ($relation == 'or' and !empty($list)) {
            return true;
        }

        $diff = array_diff($name, $list);
        if ($relation == 'and' and empty($diff)) {
            return true;
        }
        return false;
    }

    /**
     * 根据用户id获取用户组,返回值为数组
     * @param  uid int     用户id
     * @return array       用户所属的用户组 array(
     *     array('uid'=>'用户id','group_id'=>'用户组id','title'=>'用户组名称','rules'=>'用户组拥有的规则id,多个,号隔开'),
     *     ...)
     */
    public function getGroups($uid) {

        static $groups = array();
        if (isset($groups[$uid]))
            return $groups[$uid];
        $user_groups = M()
            ->table($this->_config['AUTH_ROLE_USER'])->alias("a")
            ->join($this->_config['AUTH_ROLE']." as b on a.role_id=b.role_id")
            ->where("a.admin_id='$uid' and b.status='1'")
            ->field('a.role_id')->select();

        $temp_arr = array();
        foreach($user_groups as $user_group) {
            array_push($temp_arr, $user_group['role_id']);
        }

        $groups[$uid]=$temp_arr?:array();
        return $groups[$uid];
    }


    /**
     * 获得权限列表
     * @param integer $uid  用户id
     * @param integer $type
     */
    protected function getAuthList($uid, $groups, $name) {
        //static $_authList = array(); //保存用户验证通过的权限列表
        if (isset($_authList[$uid])) {
            return $_authList[$uid];
        }

        $rules = M()
            ->table($this->_config['AUTH_ACCESS'])->alias("a")
            ->join($this->_config['AUTH_RULE']." as b on a.rule_name=b.name")
            ->where(array("a.role_id"=>array("in",$groups),"b.name"=>array("in",$name)))
            ->select();

        $_authList[$uid]=$rules?:array();
        return $_authList[$uid];
    }

    /**
     * 获得用户资料,根据自己的情况读取数据库
     */
    protected function getUserInfo($uid) {
        static $userinfo=array();
        if(!isset($userinfo[$uid])){
            $userinfo[$uid]=M()->where(array('admin_id'=>$uid))->table($this->_config['AUTH_USER'])->find();
        }
        return $userinfo[$uid];
    }

}
